package com.sdy.hospitalguard.biz.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sdy.common.model.BizException;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.EncodeUtil;
import com.sdy.common.utils.RandomUtil;
import com.sdy.hospitalguard.biz.constants.Constants;
import com.sdy.hospitalguard.biz.mapper.ApplyPostMapper;
import com.sdy.hospitalguard.biz.model.*;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.hospitalguard.biz.utils.QrCodeUtil;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 健康打卡表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2020-05-08
 */
@Slf4j
@Service
public class ApplyPostServiceImpl extends BaseServiceImpl<ApplyPost> implements ApplyPostService {
    @Autowired
    private ApplyPostMapper applyPostMapper;
    @Autowired
    private QrcodeService qrcodeService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;
    @Autowired
    private MessageNotificationService messageNotificationService;
    @Autowired
    private HospitalUserService hospitalUserService;


    @Override
    public Boolean insertData(ApplyPost applyPost) throws BizException {
        checkData(applyPost);
        Date date = new Date();
        // 检查今日是否已经打卡
        String dateDay = DateUtil.getDate(date, "yyyy-MM-dd");
        String dayTime = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
        List<ApplyPost> listApply = list(Wrappers.<ApplyPost>lambdaQuery()
                .eq(ApplyPost::getUserId, applyPost.getUserId())
                .likeRight(ApplyPost::getCreateTime, dateDay));
        Assert.isTrue(listApply.size() > 0, "您今日已打卡,请勿重复打卡!");
        applyPost.setCreateTime(date);
        // 如果打卡有意外情况，则此人今日打卡数据异常
        if (applyPost.getHealthAbnormalDetail() == 2 || applyPost.getHealthTouchPatient() == 2 || applyPost.getHealthCorridorPatient() == 2) {
            // 设置今天的打卡状态为异常
            applyPost.setApplyState(1);
        }
        boolean save = save(applyPost);
        // 检查这个人的身份
        // 是否是正在陪护
        EscortAssociated oneEscortAssociated = escortAssociatedService.getOne(Wrappers.<EscortAssociated>lambdaQuery()
                .eq(EscortAssociated::getUserId, applyPost.getUserId())
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getFlowState, 0));
        // 是否是患者
        PatientInformation onePatientInformation = patientInformationService.getOne(Wrappers.<PatientInformation>lambdaQuery()
                .eq(PatientInformation::getUserId, applyPost.getUserId())
                .eq(PatientInformation::getPatientState, 0));
        // 检查此人是否是探视者
        List<VisitAppointment> list = visitAppointmentService.list(Wrappers.<VisitAppointment>lambdaQuery()
                .eq(VisitAppointment::getUserId, applyPost.getUserId())
                .eq(VisitAppointment::getAppointmentState, 0)
                .in(VisitAppointment::getVisitState, 0, 1));
        if (applyPost.getHealthAbnormalDetail() == 2 || applyPost.getHealthTouchPatient() == 2 || applyPost.getHealthCorridorPatient() == 2) {
            // 如果陪护则发送消息给护士站
            if (oneEscortAssociated != null) {
                // 消息内容(病区 + 床 + 患者 + 陪护 + 原因)
                // 获取患者信息
                PatientInformation byId = patientInformationService.getById(oneEscortAssociated.getPatientId());
                String name = hospitalUserService.getById(byId.getUserId()).getName();
                String nameph = hospitalUserService.getById(applyPost.getUserId()).getName();
                String msg = byId.getSickbedId() + "病床的" + name + "患者的陪护" + nameph + "在" + dayTime + "出现打卡异常！";
                // 陪护发消息
                messageNotificationService.save(
                        new MessageNotification()
                                .setUserId(applyPost.getUserId())
                                .setUserType(1)
                                .setMessageContent(msg)
                                .setState(1)
                                .setMessageState(0)
                                .setCreateTime(date));
            } else if (onePatientInformation != null) {
                String name = hospitalUserService.getById(onePatientInformation.getUserId()).getName();
                String msg = onePatientInformation.getSickbedId() + "病床的" + name + "患者" + "在" + dayTime + "出现打卡异常！";
                // 患者发消息
                messageNotificationService.save(
                        new MessageNotification()
                                .setUserId(applyPost.getUserId())
                                .setUserType(1)
                                .setMessageContent(msg)
                                .setState(1)
                                .setMessageState(0)
                                .setCreateTime(date));
            } else if (list.size() > 0) {
                // 取消探视资格
                List<Integer> ids = list.stream().map(VisitAppointment::getId).collect(Collectors.toList());
                for (Integer id : ids) {
                    visitAppointmentService.updateById(new VisitAppointment().setId(id).setVisitState(3));
                }
            }
        }
        return save;
    }

    @Override
    public Boolean updateData(ApplyPost applyPost) throws BizException {
        checkData(applyPost);
        Date date = new Date();
        // 检查今日是否已经修改
        String dateDay = DateUtil.getDate(date, "yyyy-MM-dd");
        String dayTime = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
        ApplyPost one = getOne(Wrappers.<ApplyPost>lambdaQuery()
                .eq(ApplyPost::getUserId, applyPost.getUserId())
                .likeRight(ApplyPost::getCreateTime, dateDay));
        Assert.isNull(one, "您今日未打卡,请先前往打卡!");
        Assert.isTrue(one.getUpdateNum() == 1, "今日修改次数已达上限!");
        applyPost.setUpdateTime(date).setUpdateNum(one.getUpdateNum() + 1);
        // 如果打卡有意外情况，则此人今日打卡数据异常
        if (applyPost.getHealthAbnormalDetail() == 2 || applyPost.getHealthTouchPatient() == 2 || applyPost.getHealthCorridorPatient() == 2) {
            // 设置今天的打卡状态为异常
            applyPost.setApplyState(1).setUpdateTime(date).setUpdateNum(one.getUpdateNum() + 1);
        }
        boolean update = updateById(applyPost);
        // 检查这个人的身份
        // 是否是正在陪护
        EscortAssociated oneEscortAssociated = escortAssociatedService.getOne(Wrappers.<EscortAssociated>lambdaQuery()
                .eq(EscortAssociated::getUserId, applyPost.getUserId())
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getFlowState, 0));
        // 是否是患者
        PatientInformation onePatientInformation = patientInformationService.getOne(Wrappers.<PatientInformation>lambdaQuery()
                .eq(PatientInformation::getUserId, applyPost.getUserId())
                .eq(PatientInformation::getPatientState, 0));
        // 检查此人是否是探视者
        List<VisitAppointment> list = visitAppointmentService.list(Wrappers.<VisitAppointment>lambdaQuery()
                .eq(VisitAppointment::getUserId, applyPost.getUserId())
                .eq(VisitAppointment::getAppointmentState, 0)
                .in(VisitAppointment::getVisitState, 0, 1));
        if (applyPost.getHealthAbnormalDetail() == 2 || applyPost.getHealthTouchPatient() == 2 || applyPost.getHealthCorridorPatient() == 2) {
            // 如果陪护则发送消息给护士站
            if (oneEscortAssociated != null) {
                // 消息内容(病区 + 床 + 患者 + 陪护 + 原因)
                // 获取患者信息
                PatientInformation byId = patientInformationService.getById(oneEscortAssociated.getPatientId());
                String name = hospitalUserService.getById(byId.getUserId()).getName();
                String nameph = hospitalUserService.getById(applyPost.getUserId()).getName();
                String msg = byId.getSickbedId() + "病床的" + name + "患者的陪护" + nameph + "在" + dayTime + "修改打卡数据后出现打卡异常！";
                // 陪护发消息
                messageNotificationService.save(
                        new MessageNotification()
                                .setUserId(applyPost.getUserId())
                                .setUserType(1)
                                .setMessageContent(msg)
                                .setState(1)
                                .setMessageState(0)
                                .setCreateTime(date));
            } else if (onePatientInformation != null) {
                String name = hospitalUserService.getById(onePatientInformation.getUserId()).getName();
                String msg = onePatientInformation.getSickbedId() + "病床的" + name + "患者" + "在" + dayTime + "修改打卡数据后出现打卡异常！";
                // 患者发消息
                messageNotificationService.save(
                        new MessageNotification()
                                .setUserId(applyPost.getUserId())
                                .setUserType(1)
                                .setMessageContent(msg)
                                .setState(1)
                                .setMessageState(0)
                                .setCreateTime(date));
            } else if (list.size() > 0) {
                // 取消探视资格
                List<Integer> ids = list.stream().map(VisitAppointment::getId).collect(Collectors.toList());
                for (Integer id : ids) {
                    visitAppointmentService.updateById(new VisitAppointment().setId(id).setVisitState(3));
                }
            }
        }
        return update;
    }

    @Override
    public Boolean createQRcode(Integer userId) throws BizException {
        // 创建用户QR文件夹
        String folderDir = Constants.QRCODE_PATH_PASSQR;
        String filePath = folderDir + "/" + System.currentTimeMillis() + "_" + RandomUtil.produceNumber(5) + "." + Constants.QRCODE_FORMAT;
        String tk = "passQr" + UUID.randomUUID().toString().replace("-", "")
                + EncodeUtil.md5(System.currentTimeMillis() + "").substring(0, 8);
        QrCodeUtil.createQrNoImage(null, tk, filePath);
        Qrcode qrcode = new Qrcode().setQrcodePath(filePath).setQrcodeContent(tk).setQrcodeState(0).setApplyTime(new Date()).setUserId(userId);
        boolean save = qrcodeService.save(qrcode);
        Assert.notTrue(save, "二维码关联用户信息失败!");
        return true;
    }

    @Override
    public Integer checkIdentity(Integer userId) {
        // 检查这个人的身份
        // 是否是患者
        PatientInformation onePatientInformation = patientInformationService.getOne(Wrappers.<PatientInformation>lambdaQuery()
                .eq(PatientInformation::getUserId, userId)
                .eq(PatientInformation::getPatientState, 0));
        // 是否是正在陪护
        List<EscortAssociated> listEscortAssociated = escortAssociatedService.list(Wrappers.<EscortAssociated>lambdaQuery()
                .eq(EscortAssociated::getUserId, userId)
                .eq(EscortAssociated::getAttendantState, 0)
                .eq(EscortAssociated::getFlowState, 0));
        // 检查此人是否是探视者
        List<VisitAppointment> list = visitAppointmentService.list(Wrappers.<VisitAppointment>lambdaQuery()
                .eq(VisitAppointment::getUserId, userId)
                .eq(VisitAppointment::getAppointmentState, 0)
                .in(VisitAppointment::getVisitState, 0, 1));
        int num = 0;
        if (onePatientInformation != null) {
            num = 1;
        } else if (listEscortAssociated.size() > 0) {
            num = 2;
        } else if (list.size() > 0) {
            num = 3;
        } else if (listEscortAssociated.size() > 0 && list.size() > 0) {
            num = 4;
        }
        return num;
    }

    private void checkData(ApplyPost applyPost) throws BizException {
        Assert.isNull(applyPost.getHealthAbnormalDetail(), "健康状况不可为空!");
        Assert.isNull(applyPost.getHealthCorridorPatient(), "近14天所居住的楼道是否有确诊的新型冠状病毒感染的肺炎患者或密切接触者不可为空!");
        Assert.isNull(applyPost.getHealthTouchPatient(), "近14天是否接触过疑似或确诊的新型冠状病毒感染的肺炎患者或密切接触者不可为空!");
    }

}
